<template>
  <q-page :style-fn="styFn">
    <q-table
      :style="{ 'max-height': tableHeight + 'px' }"
      title="从服务器中获取数据"
      :rows="rows"
      :columns="columns"
      row-key="id"
      v-model:pagination="pagination"
      :loading="loading"
      :filter="filter"
      @request="onRequest"
      binary-state-sort
    >
      <template v-slot:top-right>
        <q-input
          borderless
          dense
          debounce="300"
          v-model="filter"
          placeholder="搜索"
        >
          <template v-slot:append>
            <q-icon name="search" />
          </template>
        </q-input>
      </template>
      <template v-slot:loading>
        <q-inner-loading showing color="primary" />
      </template>
    </q-table>
  </q-page>
</template>

<script setup lang="ts">
import { QTableProps } from 'quasar';
import { ref, onMounted } from 'vue';
const tableHeight = ref(400);
const styFn = (offset: number, height: number) => {
  tableHeight.value = height - offset;
  console.log('height: ', height);
  console.log('offset: ', offset);
};
const columns: QTableProps['columns'] = [
  {
    name: 'desc',
    required: true,
    label: '甜品',
    align: 'left',
    field: (row) => row.name,
    format: (val) => `${val}`,
    sortable: true,
  },
  {
    name: 'calories',
    align: 'center',
    label: '卡路里',
    field: 'calories',
    sortable: true,
  },
  { name: 'fat', label: '脂肪', field: 'fat', sortable: true },
  { name: 'carbs', label: '碳水', field: 'carbs', sortable: true },
  { name: 'protein', label: '蛋白质', field: 'protein', sortable: true },
  { name: 'sodium', label: '钠', field: 'sodium', sortable: true },
  {
    name: 'calcium',
    label: '钙',
    field: 'calcium',
    sortable: true,
    sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
  },
  {
    name: 'iron',
    label: '铁',
    field: 'iron',
    sortable: true,
    sort: (a, b) => parseInt(a, 10) - parseInt(b, 10),
  },
];

const originalRows = [
  {
    id: 1,
    name: '冷冻酸奶',
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    sodium: 87,
    calcium: '14%',
    iron: '1%',
  },
  {
    id: 2,
    name: '冰淇淋三明治',
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    sodium: 129,
    calcium: '8%',
    iron: '1%',
  },
  {
    id: 3,
    name: '泡芙',
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    sodium: 337,
    calcium: '6%',
    iron: '7%',
  },
  {
    id: 4,
    name: '纸杯蛋糕',
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    sodium: 413,
    calcium: '3%',
    iron: '8%',
  },
  {
    id: 5,
    name: '姜饼',
    calories: 356,
    fat: 16.0,
    carbs: 49,
    protein: 3.9,
    sodium: 327,
    calcium: '7%',
    iron: '16%',
  },
  {
    id: 6,
    name: '软糖',
    calories: 375,
    fat: 0.0,
    carbs: 94,
    protein: 0.0,
    sodium: 50,
    calcium: '0%',
    iron: '0%',
  },
  {
    id: 7,
    name: '棒棒糖',
    calories: 392,
    fat: 0.2,
    carbs: 98,
    protein: 0,
    sodium: 38,
    calcium: '0%',
    iron: '2%',
  },
  {
    id: 8,
    name: '蜂蜜',
    calories: 408,
    fat: 3.2,
    carbs: 87,
    protein: 6.5,
    sodium: 562,
    calcium: '0%',
    iron: '45%',
  },
  {
    id: 9,
    name: '甜甜圈',
    calories: 452,
    fat: 25.0,
    carbs: 51,
    protein: 4.9,
    sodium: 326,
    calcium: '2%',
    iron: '22%',
  },
  {
    id: 10,
    name: '曲奇',
    calories: 518,
    fat: 26.0,
    carbs: 65,
    protein: 7,
    sodium: 54,
    calcium: '12%',
    iron: '6%',
  },
  {
    id: 11,
    name: '冷冻酸奶-1',
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    sodium: 87,
    calcium: '14%',
    iron: '1%',
  },
  {
    id: 12,
    name: '冰淇淋三明治-1',
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    sodium: 129,
    calcium: '8%',
    iron: '1%',
  },
  {
    id: 13,
    name: '泡芙1',
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    sodium: 337,
    calcium: '6%',
    iron: '7%',
  },
  {
    id: 14,
    name: '纸杯蛋糕-1',
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    sodium: 413,
    calcium: '3%',
    iron: '8%',
  },
  {
    id: 15,
    name: '姜饼-1',
    calories: 356,
    fat: 16.0,
    carbs: 49,
    protein: 3.9,
    sodium: 327,
    calcium: '7%',
    iron: '16%',
  },
  {
    id: 16,
    name: '软糖-1',
    calories: 375,
    fat: 0.0,
    carbs: 94,
    protein: 0.0,
    sodium: 50,
    calcium: '0%',
    iron: '0%',
  },
  {
    id: 17,
    name: '棒棒糖-1',
    calories: 392,
    fat: 0.2,
    carbs: 98,
    protein: 0,
    sodium: 38,
    calcium: '0%',
    iron: '2%',
  },
  {
    id: 18,
    name: '蜂蜜-1',
    calories: 408,
    fat: 3.2,
    carbs: 87,
    protein: 6.5,
    sodium: 562,
    calcium: '0%',
    iron: '45%',
  },
  {
    id: 19,
    name: '甜甜圈-1',
    calories: 452,
    fat: 25.0,
    carbs: 51,
    protein: 4.9,
    sodium: 326,
    calcium: '2%',
    iron: '22%',
  },
  {
    id: 20,
    name: '曲奇-1',
    calories: 518,
    fat: 26.0,
    carbs: 65,
    protein: 7,
    sodium: 54,
    calcium: '12%',
    iron: '6%',
  },
  {
    id: 21,
    name: '冷冻酸奶-2',
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    sodium: 87,
    calcium: '14%',
    iron: '1%',
  },
  {
    id: 22,
    name: '冰淇淋三明治-2',
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    sodium: 129,
    calcium: '8%',
    iron: '1%',
  },
  {
    id: 23,
    name: '泡芙2',
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    sodium: 337,
    calcium: '6%',
    iron: '7%',
  },
  {
    id: 24,
    name: '纸杯蛋糕-2',
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    sodium: 413,
    calcium: '3%',
    iron: '8%',
  },
  {
    id: 25,
    name: '姜饼-2',
    calories: 356,
    fat: 16.0,
    carbs: 49,
    protein: 3.9,
    sodium: 327,
    calcium: '7%',
    iron: '16%',
  },
  {
    id: 26,
    name: '软糖-2',
    calories: 375,
    fat: 0.0,
    carbs: 94,
    protein: 0.0,
    sodium: 50,
    calcium: '0%',
    iron: '0%',
  },
  {
    id: 27,
    name: '棒棒糖-2',
    calories: 392,
    fat: 0.2,
    carbs: 98,
    protein: 0,
    sodium: 38,
    calcium: '0%',
    iron: '2%',
  },
  {
    id: 28,
    name: '蜂蜜-2',
    calories: 408,
    fat: 3.2,
    carbs: 87,
    protein: 6.5,
    sodium: 562,
    calcium: '0%',
    iron: '45%',
  },
  {
    id: 29,
    name: '甜甜圈-2',
    calories: 452,
    fat: 25.0,
    carbs: 51,
    protein: 4.9,
    sodium: 326,
    calcium: '2%',
    iron: '22%',
  },
  {
    id: 30,
    name: '曲奇-2',
    calories: 518,
    fat: 26.0,
    carbs: 65,
    protein: 7,
    sodium: 54,
    calcium: '12%',
    iron: '6%',
  },
  {
    id: 31,
    name: '冷冻酸奶-3',
    calories: 159,
    fat: 6.0,
    carbs: 24,
    protein: 4.0,
    sodium: 87,
    calcium: '14%',
    iron: '1%',
  },
  {
    id: 32,
    name: '冰淇淋三明治-3',
    calories: 237,
    fat: 9.0,
    carbs: 37,
    protein: 4.3,
    sodium: 129,
    calcium: '8%',
    iron: '1%',
  },
  {
    id: 33,
    name: '泡芙3',
    calories: 262,
    fat: 16.0,
    carbs: 23,
    protein: 6.0,
    sodium: 337,
    calcium: '6%',
    iron: '7%',
  },
  {
    id: 34,
    name: '纸杯蛋糕-3',
    calories: 305,
    fat: 3.7,
    carbs: 67,
    protein: 4.3,
    sodium: 413,
    calcium: '3%',
    iron: '8%',
  },
  {
    id: 35,
    name: '姜饼-3',
    calories: 356,
    fat: 16.0,
    carbs: 49,
    protein: 3.9,
    sodium: 327,
    calcium: '7%',
    iron: '16%',
  },
  {
    id: 36,
    name: '软糖-3',
    calories: 375,
    fat: 0.0,
    carbs: 94,
    protein: 0.0,
    sodium: 50,
    calcium: '0%',
    iron: '0%',
  },
  {
    id: 37,
    name: '棒棒糖-3',
    calories: 392,
    fat: 0.2,
    carbs: 98,
    protein: 0,
    sodium: 38,
    calcium: '0%',
    iron: '2%',
  },
  {
    id: 38,
    name: '蜂蜜-3',
    calories: 408,
    fat: 3.2,
    carbs: 87,
    protein: 6.5,
    sodium: 562,
    calcium: '0%',
    iron: '45%',
  },
  {
    id: 39,
    name: '甜甜圈-3',
    calories: 452,
    fat: 25.0,
    carbs: 51,
    protein: 4.9,
    sodium: 326,
    calcium: '2%',
    iron: '22%',
  },
  {
    id: 40,
    name: '曲奇-3',
    calories: 518,
    fat: 26.0,
    carbs: 65,
    protein: 7,
    sodium: 54,
    calcium: '12%',
    iron: '6%',
  },
];

type rowType = (typeof originalRows)[0];

const rows = ref<typeof originalRows>([]);
const filter = ref('');
const loading = ref(false);
const pagination = ref({
  sortBy: 'desc',
  descending: false,
  page: 1,
  rowsPerPage: 3,
  rowsNumber: 10,
});
// emulate ajax call
// SELECT * FROM ... WHERE...LIMIT...
const fetchFromServer = (
  startRow: number,
  count: number,
  filter: string,
  sortBy: string,
  descending: boolean
) => {
  const data = filter
    ? originalRows.filter((row) => row.name.includes(filter))
    : originalRows.slice();

  // handle sortBy
  if (sortBy) {
    const sortFn =
      sortBy === 'desc'
        ? descending
          ? (a: rowType, b: rowType) =>
              a.name > b.name ? -1 : a.name < b.name ? 1 : 0
          : (a: rowType, b: rowType) =>
              a.name > b.name ? 1 : a.name < b.name ? -1 : 0
        : descending
        ? (a: rowType, b: rowType) =>
            parseFloat(b[sortBy as keyof rowType] as string) -
            parseFloat(a[sortBy as keyof rowType] as string)
        : (a: rowType, b: rowType) =>
            parseFloat(a[sortBy as keyof rowType] as string) -
            parseFloat(b[sortBy as keyof rowType] as string);
    data.sort(sortFn);
  }

  return data.slice(startRow, startRow + count);
};

// emulate 'SELECT count(*) FROM ...WHERE...'
function getRowsNumberCount(filter: string) {
  if (!filter) {
    return originalRows.length;
  }
  let count = 0;
  originalRows.forEach((treat) => {
    if (treat.name.includes(filter)) {
      ++count;
    }
  });
  return count;
}

function onRequest(props: Parameters<Required<QTableProps>['onRequest']>[0]) {
  console.log('props: ', props);

  const { page, rowsPerPage, sortBy, descending } = props.pagination;
  const filter = props.filter;

  loading.value = true;

  props.getCellValue('1', '2');
  // emulate server
  setTimeout(() => {
    // update rowsCount with appropriate value
    pagination.value.rowsNumber = getRowsNumberCount(filter);

    // get all rows if "All" (0) is selected
    const fetchCount =
      rowsPerPage === 0 ? pagination.value.rowsNumber : rowsPerPage;

    // calculate starting row of data
    const startRow = (page - 1) * rowsPerPage;

    // fetch data from "server"
    const returnedData = fetchFromServer(
      startRow,
      fetchCount,
      filter,
      sortBy,
      descending
    );

    // clear out existing data and add new
    rows.value.splice(0, rows.value.length - 1, ...returnedData);

    // don't forget to update local pagination object
    pagination.value.page = page;
    pagination.value.rowsPerPage = rowsPerPage;
    pagination.value.sortBy = sortBy;
    pagination.value.descending = descending;

    // ...and turn of loading indicator
    loading.value = false;
  }, 1500);
}

onMounted(() => {
  // get initial data from server (1st page)
  onRequest({
    pagination: pagination.value,
    filter: '',
    getCellValue(col, row) {
      console.log('row: ', row);
      console.log('col: ', col);
    },
  });
});
</script>

<style scoped></style>
